#pragma once
#include <string>
#include <vector>
#include <cstdlib>
#include <sys/wait.h>
#include "Task.hpp"
#include "Channel.hpp"

//包装器
using work_t = std::function<void()>;

//错误码
enum
{
    OK = 0,
    UsageError,
    PipeError,
    ForkError
};

//进程池
class ProcessPool
{
public:
    ProcessPool(int num, work_t work = Worker)
        : _num(num),
          _work(work)
    {
    }

    // 初始化管道和子进程
    int InitProcessPool()
    {
        for (int i = 0; i < _num; i++)
        {
            // 先创建管道
            int p[2] = {0};
            int n = pipe(p);
            if (n != 0)
            {
                return PipeError;
            }

            // 创建子进程
            int id = fork();
            if (id == 0) // 子进程
            {
                // 将不用的端口关闭
                close(p[1]);
                // 将子进程继承下来的写端都关闭了
                for (auto &e : channels)
                {
                    close(e._fd);
                }

                // 重定向到0端口
                dup2(p[0], 0);

                // 执行任务
                _work();

                exit(0);
            }
            else if (id > 0) // 父进程
            {
                // 关掉不用的读端
                close(p[0]);

                // 对子进程管理
                channels.emplace_back(Channel(p[1], id));
            }
            else
            {
                return ForkError;
            }
        }

        return OK;
    }

    // 执行任务
    void DispatchTask()
    {
        // 轮询
        int count = 10;
        int index = 0;
        while (count--)
        {
            // 获取任务
            int n = tk.SelectTask();
            std::cout << "n: " << n << std::endl;

            // 派发任务
            Channel channel = channels[index];
            std::cout << "index:" << index << " fd: " << channel._fd << " id: " << channel._id << std::endl;
            channel.Send(n);

            index++;
            index %= _num;
            sleep(2);
        }
    }

    // 结束任务
    void CleanProcessPool()
    {
        for (auto &e : channels)
        {
            close(e._fd);
            waitpid(e._id,nullptr,0);
        }
    }


    void Debug()
    {
        std::cout << "num: " << _num << std::endl;
        for (auto &e : channels)
        {
            std::cout << "fd: " << e._fd << "id: " << e._id << std::endl;
        }
    }

private:
    int _num;                      // 子进程个数
    work_t _work;                  // 使用方法
    std::vector<Channel> channels; // 管理子进程和管道
};
